
#if defined(WIN32) || defined(WIN64)
#pragma unmanaged
#endif

#include <Liberty3D/Engine/ISerializer.h>
#include <Liberty3D/Engine/Uuid.h>
#include <Liberty3D/Engine/Quaternion.h>
#include <Liberty3D/Engine/Vector3.h>
#include <Liberty3D/Engine/XML/INode.h>
#include <Liberty3D/Engine/XML/Parser.h>
#include <Liberty3D/Engine/XML/Serializer.h>

#include <fstream>

using namespace Liberty::Engine;
using namespace Liberty::Engine::Xml;

bool ISerializer::serialize(const char* name, Vector3& v) {
    bool result = true;

    beginStruct(name, "Vector3");
    result &= serialize("x", v[0]);
    result &= serialize("y", v[1]);
    result &= serialize("z", v[2]);
    endStruct(name, "Vector3");

    return result;
}

bool ISerializer::serialize(const char* name, Quaternion& v) {
    bool result = true;

    beginStruct(name, "Quaternion");
    result &= serialize("x", v[0]);
    result &= serialize("y", v[1]);
    result &= serialize("z", v[2]);
    result &= serialize("w", v[3]);
    endStruct(name, "Quaternion");

    return result;
}

bool ISerializer::serialize(const char* name, Uuid& v, bool mandatory) {
    bool result = true;
    
    if (isReading()) {
        std::string s;
        
        result &= serialize(name, s);
        v = Uuid(s);
    }
    else {
        std::string s(v.toString());
        
        result &= serialize(name, s);
    }
    
    return result;
}

ISerializer* ISerializer::readerForFile(const std::string& fileName, ISerializableFactory* factory) {
    return new Xml::Reader(Parser::parse(fileName), factory);
}

ISerializer* ISerializer::readerForStream(std::streambuf* fileBuffer, ISerializableFactory* factory) {
    return new Xml::Reader(Parser::parse(fileBuffer), factory);
}

namespace Liberty { namespace Engine { namespace Internal {
    class WriterToFile : public Xml::Writer {
    public:
        std::string _fileName;

    public:
        WriterToFile(const std::string& fileName) : _fileName(fileName) {
        }

        virtual ~WriterToFile() {
            close();
            _doc->toXml(_fileName);
        }
    };

    class WriterToStream : public Xml::Writer {
    public:
        std::streambuf* _buf;

    public:
        WriterToStream(std::streambuf* buf) : _buf(buf) {
        }

        virtual ~WriterToStream() {
            close();
            _doc->toXml(_buf);
        }
    };
}}}

ISerializer* ISerializer::writerForFile(const std::string& fileName) {
    return new Liberty::Engine::Internal::WriterToFile(fileName);
}

ISerializer* ISerializer::writerForStream(std::streambuf* fileBuffer) {
    return new Liberty::Engine::Internal::WriterToStream(fileBuffer);
}
